import { loggerProvider } from '@app/common/constants';
import { HttpExceptionFilter } from '@app/common/filters/httpexception/httpexception.filter';
import { AuthRestfulGuard } from '@app/common/guards/auth.restful';
import {
  BookReservation,
  Reservation,
  ReservationStatus,
} from '@app/common/types/graphqls/graphql.schema';
import { ReservationService } from '@app/services/reservation/reservation.service';
import {
  Body,
  Controller,
  Get,
  Inject,
  Logger,
  Param,
  Post,
  Put,
  Query,
  UseFilters,
  UseGuards,
} from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';
import { ObjectId } from 'mongoose';
@Controller('reservation')
@UseGuards(AuthRestfulGuard)
@UseFilters(new HttpExceptionFilter())
export class ReservationController {
  constructor(
    @Inject(REQUEST) private readonly request: Request,
    private readonly reservationService: ReservationService,
    @Inject(loggerProvider)
    private readonly logger: Logger,
  ) {}

  @Post()
  async book(@Body() reservation: BookReservation): Promise<Reservation> {
    const model = new Reservation();
    Object.assign(model, reservation);
    model.reservedBy = this.request['user'] || 'System';
    return await this.reservationService.create(model);
  }

  @Put(':id')
  async update(
    @Param('id') id: ObjectId,
    @Body() reservation: Omit<Reservation, '_id'>,
  ): Promise<Reservation> {
    const model = new Reservation();
    Object.assign(model, reservation);
    return await this.reservationService.update(id, model);
  }

  @Put('cancel/:id')
  async cancel(@Param('id') id: ObjectId): Promise<Reservation> {
    return await this.reservationService.updateStatus(
      id,
      ReservationStatus.Canceled,
    );
  }

  @Put('mark/:id')
  async mark(
    @Param('id') id: ObjectId,
    @Body('status') status: ReservationStatus,
  ): Promise<Reservation> {
    return await this.reservationService.updateStatus(id, status);
  }

  @Get(':id')
  async detail(@Param('id') id: ObjectId): Promise<Reservation> {
    return await this.reservationService.query(id);
  }

  @Get()
  reservation(
    @Query('date') date: Date | string,
    @Query('status') status: ReservationStatus,
  ): Promise<Reservation[]> {
    return this.reservationService.queryBy(date, status);
  }
}
